local gamelib = require "club.threecard.gamelib"
local pokerlib = require "club.threecard.pokerlib"
local poker_manager = pokerlib.core.poker_manager

local poker_container = gamelib.ui.element()

local log = gamelib.logging.get("poker_container")

local function dumpHand(self)
    local t = {}
    for _, poker in pairs(self.hand) do
        table.insert(t, poker:tostring());
    end
    
    return table.concat(t, ",");
end

local default_res = "club.threecard.pokerlib/ui/common.b:poker_container"

function poker_container:ctor(config)
    self.config = config or pokerlib.core.poker_container_config.new();
    self.res = self.config.container_res or default_res;

    self.hand = {};     --手牌
    self.lastChu = {};  --上一手出牌
    self.ming = {};     --明牌

    -- 依赖的Transform节点，injected之后会有
    self.hand_tran = nil;
    self.ming_tran = nil;
    self.lastchu_tran = nil;

    self.startPoker = nil;
    self.lastPoker = nil;
    self.will_selected_poker = {};
end

function poker_container:on_set_gameobject()
    self:super("on_set_gameobject")
    self.loaded = true
end

function poker_container:clear()
    for _, poker in ipairs(self.hand) do
        poker_manager.put(poker);
    end
    self.hand = {};

    for _, poker in ipairs(self.lastChu) do
        poker_manager.put(poker);
    end
    self.lastChu = {};

    for _, poker in ipairs(self.ming) do
        poker_manager.put(poker);
    end
    self.ming = {};

    self.should_mopai_t = nil;
    self.should_chupai_t = nil;
    self.should_clear_chupai = nil;
end

-- 直接填充数据不带动画
function poker_container:fill(handServerValueTable, chuServerValueTable)
    handServerValueTable = handServerValueTable or {};
    chuServerValueTable = chuServerValueTable or {};

    if not self.loaded then
        self.should_fill = {handServerValueTable = handServerValueTable, chuServerValueTable = chuServerValueTable}
        return;
    end

    self:insert_hand(handServerValueTable);

    for _, serverValue in ipairs(chuServerValueTable) do
        local poker_data = self.config.poker_data_class.new(serverValue);
        local poker = poker_manager.get(poker_data, self.config.chu_poker_class);
        table.insert(self.lastChu, poker);
    end

    if self.config.chu_sort then
        table.sort(self.lastChu, self.config.chu_sort);
    end

    if self.config.chu_align then
        self.config.chu_align(self.lastChu, self.lastchu_tran);
    end
end

-- 摸牌
function poker_container:mopai(serverValueTable)
    if not self.loaded then
        self.should_mopai_t = serverValueTable;
        return;
    end

    if self.config.mopai_anim then
        self.config.mopai_anim(self, serverValueTable, function() self:insert_hand(serverValueTable) end);
    else
        self:insert_hand(serverValueTable);
    end
end

-- 出牌
function poker_container:chupai(serverValueTable)
    if not self.loaded then
        self.should_chupai_t = serverValueTable;
        return;
    end

    self:clear_chupai();

    local removeCount = 0;
    for _, serverValue in ipairs(serverValueTable) do
        if self.config.show_hand then
            local found = false;
            for index, poker in ipairs(self.hand) do
                if poker.data.server_value == serverValue then
                    poker_manager.put(poker);
                    table.remove(self.hand, index);
                    removeCount = removeCount + 1;
                    found = true;
                    break;
                end
            end

            if not found and self.hand[#self.hand] then
                poker_manager.put(self.hand[#self.hand])
                table.remove(self.hand, #self.hand)
                removeCount = removeCount + 1
            end
        end

        local poker_data = self.config.poker_data_class.new(serverValue);
        local poker = poker_manager.get(poker_data, self.config.chu_poker_class);
        table.insert(self.lastChu, poker);
    end

    if self.config.show_hand then
        local pokers = self:get_selected_poker();
        for _, poker in ipairs(pokers) do
            poker:unselect();
        end

        if self.config.hand_sort then
            table.sort(self.hand, self.config.hand_sort);
        end

        if self.config.hand_align then
            self.config.hand_align(self.hand, self.hand_tran);
        end
    end

    if self.config.chu_sort then
        table.sort(self.lastChu, self.config.chu_sort);
    end

    if self.config.chu_align then
        self.config.chu_align(self.lastChu, self.lastchu_tran);
    end
end

-- 明牌
function poker_container:mingpai(serverValueTable)
    if not serverValueTable then
        return;
    end

    if #serverValueTable == 0 then
        return;
    end

    for _, serverValue in ipairs(serverValueTable) do
        local poker_data = self.config.poker_data_class.new(serverValue);
        local poker = poker_manager.get(poker_data, self.config.ming_poker_class);
        table.insert(self.ming, poker);
    end

    if self.config.ming_sort then
        table.sort(self.ming, self.config.ming_sort);
    end

    if self.config.ming_align then
        self.config.ming_align(self.ming, self.ming_tran);
    end
end

-- 清理上一手出的牌
function poker_container:clear_chupai()
    if not self.loaded then
        self.should_clear_chupai = true;
        return;
    end
    if self.lastChu == nil or #self.lastChu == 0 then
        return;
    end

    for _, poker in ipairs(self.lastChu) do
        poker_manager.put(poker);
    end

    self.lastChu = {};
end

function poker_container:unselect_all()
    for _, poker in ipairs(self.hand) do
        if poker.selected then
            poker:unselect()
        end
    end

    if self.config.select_change then
        self.config.select_change(self)
    end
    self.will_selected_poker = {}
end

function poker_container:insert_hand(serverValueTable)
    if not self.config.show_hand then
        return;
    end

    for _, serverValue in ipairs(serverValueTable) do
        local poker_data = self.config.poker_data_class.new(serverValue);
        local poker = poker_manager.get(poker_data, self.config.hand_poker_class);
        table.insert(self.hand, poker);

        self:listen_hand(poker);
    end

    if self.config.hand_sort then
        table.sort(self.hand, self.config.hand_sort);
    end

    if self.config.hand_align then
        self.config.hand_align(self.hand, self.hand_tran);
    end
end

function poker_container:get_selected_poker()
    local ret = {};
    for _, poker in ipairs(self.hand) do
        if poker.selected then
            table.insert(ret, poker);
        end
    end

    return ret;
end

function poker_container:listen_hand(poker)
    poker.click = function(poker) self:on_poker_click(poker) end
    poker.down = function(poker) self:on_poker_down(poker) end
    poker.up = function(poker) self:on_poker_up(poker) end
    poker.enter = function(poker) self:on_poker_enter(poker) end
    poker.exit = function(poker) self:on_poker_exit(poker) end
end

---------------------------------------扑克手牌操作----------------------------------------
function poker_container:on_poker_click(poker)
    if not self.config.ope_valid then
        return;
    end

    poker:on_click();
end

function poker_container:on_poker_down(poker)
    if not self.config.ope_valid then
        return;
    end

    self.pressed = true;
    self.startPoker = poker;
    self.lastPoker = nil;
    self:on_poker_enter(poker)
end

function poker_container:on_poker_up(poker)
    if not self.pressed then
        return;
    end

    self.pressed = false;
    for _, poker in pairs(self.will_selected_poker) do
        poker:select();
    end

    self.startPoker = nil;
    self.lastPoker = nil;
    if self.config.select_change then
        self.config.select_change(self)
    end
end

function poker_container:on_poker_enter(poker)
    self.enterd = true;
    if not self.pressed then
        return;
    end

    if self.lastPoker ~= poker then
        self.lastPoker = poker;
        self:will_select_range(self.startPoker, self.lastPoker);
    end
end

function poker_container:on_poker_exit(poker)
    self.enterd = false;
end

function poker_container:will_select_range(startPoker, lastPoker)
    for _, poker in ipairs(self.will_selected_poker) do
        poker:will_select(false);
    end

    self.will_selected_poker = {};

    local startIndex = 1;
    local endIndex = 1;

    local a = false;
    local b = false;
    for index, poker in ipairs(self.hand) do
        if startPoker == poker then
            startIndex = index;
        end

        if lastPoker == poker then
            endIndex = index;
        end

        if a and b then
            break;
        end
    end

    if self.config.max_select_count ~= -1 then
        if startIndex > endIndex then
            if startIndex - endIndex + 1 > self.config.max_select_count then
                startIndex = endIndex + self.config.max_select_count - 1
            end
        else
            if endIndex - startIndex + 1 > self.config.max_select_count then
                startIndex = endIndex - self.config.max_select_count + 1
            end
        end    
    end

    if startIndex > endIndex then
        startIndex, endIndex = endIndex, startIndex;
    end

    if self.config.max_select_count ~= -1 then
        if endIndex - startIndex + 1 > self.config.max_select_count then
            startIndex = endIndex - self.config.max_select_count + 1
        end
    end

    if self.config.max_select_count ~= -1 then
        if endIndex - startIndex + 1 > self.config.max_select_count then
            startIndex = endIndex - self.config.max_select_count + 1
        end
    end

    for i = startIndex, endIndex do
        local poker = self.hand[i];
        poker:will_select(true);
        table.insert(self.will_selected_poker, poker);
    end
end

---------------------------------------element----------------------------------------
function poker_container:set_gameobject(gameobject, inject)
    self:super("set_gameobject", gameobject, inject);
    if self.should_mopai_t then
        self:mopai(self.should_mopai_t);
        self.should_mopai_t = nil;
    end

    if self.should_fill then
       self:fill(self.should_fill.handServerValueTable, self.should_fill.chuServerValueTable);
       self.should_fill = nil;
    end

    if self.should_chupai_t then
        self:chupai(self.should_chupai_t);
        self.should_chupai_t = nil;
    end

    if self.should_clear_chupai then
        self:clear_chupai();
        self.should_clear_chupai = nil;
    end
end
return poker_container
